<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>K230视频流客户端</title>
    <style>
        body { margin: 0; padding: 10px; font-family: Arial, sans-serif; text-align: center; background: #f0f0f0; }
        .container { max-width: 100%; margin: 0 auto; padding: 10px; }
        h1 { color: #333; font-size: 24px; margin-bottom: 10px; }
        #videoCanvas { max-width: 100%; background: #000; margin: 0 auto 10px; display: block; border: 1px solid #999; }
        .info { margin: 10px 0; font-size: 14px; color: #666; }
        #stats { font-weight: bold; color: green; }
        #debugInfo { background: #eee; padding: 10px; margin: 10px 0; border-radius: 4px; font-size: 12px; text-align: left; height: 150px; overflow-y: auto; }
        .btn { background: #4CAF50; border: none; color: white; padding: 10px 15px; text-align: center; 
               display: inline-block; font-size: 16px; margin: 10px 2px; cursor: pointer; border-radius: 4px; }
        input { padding: 10px; width: 200px; margin-right: 10px; }
        .btn.disconnect { background-color: #f44336; }
    </style>
</head>
<body>
    <div class="container">
        <h1>K230视频流客户端</h1>
        
        <div>
            <input type="text" id="ipAddress" value="192.168.169.1" placeholder="K230 IP地址">
            <button class="btn" id="connectBtn" onclick="connect()">连接</button>
            <button class="btn disconnect" id="disconnectBtn" style="display:none;" onclick="disconnect()">断开</button>
        </div>
        
        <canvas id="videoCanvas" width="640" height="360"></canvas>
        <div class="info">状态: <span id="stats">未连接</span></div>
        <div id="debugInfo"></div>
    </div>

    <script>
        // 全局变量
        var canvas = document.getElementById('videoCanvas');
        var ctx = canvas.getContext('2d');
        var stats = document.getElementById('stats');
        var ws = null;
        var connectBtn = document.getElementById('connectBtn');
        var disconnectBtn = document.getElementById('disconnectBtn');
        var reconnectTimer = null;
        var connectionAttempts = 0;
        var maxAttempts = 5;
        
        // 调试信息
        function log(msg) {
            var debug = document.getElementById('debugInfo');
            var time = new Date().toLocaleTimeString();
            debug.innerHTML += time + ": " + msg + '<br>';
            debug.scrollTop = debug.scrollHeight;
            console.log(time + ": " + msg);
        }

        // 清除调试信息
        function clearLog() {
            var debug = document.getElementById('debugInfo');
            debug.innerHTML = '';
        }
        
        // 绘制初始画布
        function drawInitialCanvas() {
            ctx.fillStyle = '#333';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = '#fff';
            ctx.font = '20px Arial';
            ctx.textAlign = 'center';
            ctx.fillText('点击"连接"按钮开始', canvas.width/2, canvas.height/2);
        }
        
        // 初始化
        drawInitialCanvas();
        
        // 连接WebSocket
        function connect() {
            // 清理之前的连接
            disconnect();
            clearLog();
            
            // 重置尝试计数
            connectionAttempts = 0;
            
            // 开始连接过程
            attemptConnect();
            
            // 更新按钮状态
            connectBtn.style.display = 'none';
            disconnectBtn.style.display = 'inline-block';
        }
        
        // 断开WebSocket
        function disconnect() {
            // 清除重连计时器
            if (reconnectTimer) {
                clearTimeout(reconnectTimer);
                reconnectTimer = null;
            }
            
            // 关闭WebSocket
            if (ws) {
                try {
                    ws.onclose = null; // 阻止触发自动重连
                    ws.close();
                } catch(e) {
                    log("关闭连接时出错: " + e.message);
                }
                ws = null;
            }
            
            // 更新状态
            stats.innerHTML = "未连接";
            
            // 更新按钮状态
            connectBtn.style.display = 'inline-block';
            disconnectBtn.style.display = 'none';
            
            // 显示断开状态
            drawInitialCanvas();
        }
        
        // 尝试连接
        function attemptConnect() {
            // 检查尝试次数
            if (connectionAttempts >= maxAttempts) {
                log("达到最大尝试次数(" + maxAttempts + ")，停止重连");
                stats.innerHTML = "连接失败，请手动重试";
                connectBtn.style.display = 'inline-block';
                disconnectBtn.style.display = 'none';
                return;
            }
            
            connectionAttempts++;
            
            var ip = document.getElementById('ipAddress').value;
            var wsUrl = "ws://" + ip + ":6001";
            
            stats.innerHTML = "正在连接... (尝试 " + connectionAttempts + "/" + maxAttempts + ")";
            log("连接WebSocket: " + wsUrl);
            
            try {
                ws = new WebSocket(wsUrl);
                ws.binaryType = "arraybuffer";
                
                // 连接超时处理
                var connectTimeout = setTimeout(function() {
                    if (ws && ws.readyState !== WebSocket.OPEN) {
                        log("连接超时");
                        ws.close();
                        scheduleReconnect();
                    }
                }, 10000); // 10秒超时
                
                ws.onopen = function() {
                    clearTimeout(connectTimeout);
                    connectionAttempts = 0; // 连接成功，重置尝试次数
                    stats.innerHTML = "已连接";
                    log("WebSocket连接已建立");
                };
                
                ws.onmessage = function(e) {
                    if (typeof e.data === "string") {
                        try {
                            var config = JSON.parse(e.data);
                            log("收到配置: " + JSON.stringify(config));
                            if (config.width && config.height) {
                                canvas.width = config.width;
                                canvas.height = config.height;
                                log("调整画布大小: " + config.width + "x" + config.height);
                            }
                        } catch (err) {
                            log("解析配置错误: " + err);
                        }
                    } else if (e.data instanceof ArrayBuffer) {
                        // 收到视频数据
                        var dataView = new DataView(e.data);
                        var dataSize = e.data.byteLength;
                        
                        stats.innerHTML = "已接收数据: " + dataSize + " 字节";
                        
                        // 绘制接收信息
                        ctx.fillStyle = '#333';
                        ctx.fillRect(0, 0, canvas.width, canvas.height);
                        ctx.fillStyle = '#0f0';
                        ctx.font = '20px Arial';
                        ctx.textAlign = 'center';
                        ctx.fillText('收到H.265数据: ' + dataSize + ' 字节', canvas.width/2, canvas.height/2);
                        
                        // 尝试检查NALU起始码
                        if (dataSize > 4) {
                            var startCode = '';
                            for (var i = 0; i < 4; i++) {
                                startCode += dataView.getUint8(i).toString(16).padStart(2, '0') + ' ';
                            }
                            ctx.fillStyle = '#ff0';
                            ctx.font = '16px Arial';
                            ctx.fillText('起始码: ' + startCode, canvas.width/2, canvas.height/2 + 30);
                        }
                    }
                };
                
                ws.onclose = function(event) {
                    clearTimeout(connectTimeout);
                    stats.innerHTML = "连接已关闭 (代码: " + event.code + ")";
                    log("WebSocket连接已关闭，代码: " + event.code);
                    
                    // 显示断开连接信息
                    ctx.fillStyle = '#333';
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                    ctx.fillStyle = '#ff4444';
                    ctx.font = '20px Arial';
                    ctx.textAlign = 'center';
                    ctx.fillText('连接已断开', canvas.width/2, canvas.height/2);
                    ctx.fillText('代码: ' + event.code, canvas.width/2, canvas.height/2 + 30);
                    
                    scheduleReconnect();
                };
                
                ws.onerror = function(err) {
                    clearTimeout(connectTimeout);
                    stats.innerHTML = "连接错误";
                    log("WebSocket错误");
                };
            } catch (error) {
                log("创建WebSocket时出错: " + error.message);
                scheduleReconnect();
            }
        }
        
        // 安排重连
        function scheduleReconnect() {
            // 如果用户已手动断开，不自动重连
            if (!disconnectBtn.style.display || disconnectBtn.style.display === 'none') {
                return;
            }
            
            var delay = connectionAttempts * 2000; // 递增延迟：2秒、4秒、6秒...
            log("计划 " + (delay/1000) + " 秒后重新连接...");
            
            // 设置重连计时器
            if (reconnectTimer) {
                clearTimeout(reconnectTimer);
            }
            
            reconnectTimer = setTimeout(function() {
                if (connectionAttempts < maxAttempts) {
                    log("尝试重新连接...");
                    attemptConnect();
                } else {
                    log("达到最大尝试次数，停止重连");
                    disconnect();
                }
            }, delay);
        }
    </script>
</body>
</html> 